import modules.script
import json
import copy
import util.chash
import dto.transaction
import modules.appconfig
import modules.db
import modules.blockchain
import dto.utx
import dto.transaction
class COutPoint:
    def __init__(self,txhash,outindex):
        #交易hash
        self.__txhash = txhash

        #索引
        self.__outindex = outindex   

    @property
    def txhash(self):
        return self.__txhash

    @txhash.setter
    def txhash(self,value):
        self.txhash =value
    
    @property
    def outindex(self):
        return self.__outindex

    @outindex.setter
    def outindex(self,value):
        self.__outindex =value


    #Object——>jsonStr
    def serializeToJsonStr(self):
        sttr=json.dumps(self, default=lambda obj: obj.__dict__)
        return sttr.replace("_COutPoint__","")

    #jsonStr——> Object
    @classmethod
    def deserializeFromJsonStr(cls,jsonStrobjectdata):
        d = json.loads(jsonStrobjectdata)
        #print(d['txins'])
        return  cls(d['txhash'],d['outindex'])
       
    
    #Object——>Python Object
    def serializeToPyObject(self):
        return json.loads(self.serializeToJsonStr())
    
    #Python Object——>Object
    @classmethod
    def deserializeFromPyObject(cls,pyObject):
       return cls.deserializeFromJsonStr(json.dumps(pyObject))

    

class CTxIn:
    def __init__(self,prevout,scriptSig):
        
        #COutPoint
        self.__prevout  = prevout

        #解锁脚本CScriptSig
        self.__scriptSig = scriptSig
    
    @property
    def prevout(self):
        return self.__prevout

    @prevout.setter
    def prevout(self,value):
        self.prevout =value
    
    @property
    def scriptSig(self):
        return self.__scriptSig

    @scriptSig.setter
    def scriptSig(self,value):
        self.__scriptSig =value

    #Object——>jsonStr
    def serializeToJsonStr(self):
        sttr=json.dumps(self, default=lambda obj: obj.__dict__)
        return sttr.replace("_CTxIn__","").replace("_COutPoint__","")

    #jsonStr——> Object
    @classmethod
    def deserializeFromJsonStr(cls,jsonStrobjectdata):
        d = json.loads(jsonStrobjectdata)
        #print(d['txins'])
        return  cls(d['prevout'],d['scriptSig'])
       
    
    #Object——>Python Object
    def serializeToPyObject(self):
        return json.loads(self.serializeToJsonStr())
    
    #Python Object——>Object
    @classmethod
    def deserializeFromPyObject(cls,pyObject):
       return cls.deserializeFromJsonStr(json.dumps(pyObject))

   
    

class CTxOut:
    def __init__(self,value,content,scriptPubKey):
        self.__value = value
        self.__content=content
        #锁定脚本 CScriptPubKey
        self.__scriptPubKey = scriptPubKey
    
    @property
    def value(self):
        return self.__value

    @value.setter
    def value(self,value):
        self.__value =value
    
    @property
    def content(self):
        return self.__content

    @content.setter
    def content(self,value):
        self.__content =value
    
    @property
    def scriptPubKey(self):
        return self.__scriptPubKey

    @scriptPubKey.setter
    def scriptPubKey(self,value):
        self.__scriptPubKey =value

        
    #Object——>jsonStr
    def serializeToJsonStr(self):
        sttr=json.dumps(self, default=lambda obj: obj.__dict__)
        return sttr.replace("_CScriptPubKey__","").replace("_CTxOut__","")

    #jsonStr——> Object
    @classmethod
    def deserializeFromJsonStr(cls,jsonStrobjectdata):
        d = json.loads(jsonStrobjectdata)
        #print(d['txins'])
        return  cls(d['value'],d['content'],d['scriptPubKey'])
       
    
    #Object——>Python Object
    def serializeToPyObject(self):
        return json.loads(self.serializeToJsonStr())
    
    #Python Object——>Object
    @classmethod
    def deserializeFromPyObject(cls,pyObject):
       return cls.deserializeFromJsonStr(json.dumps(pyObject))

   
   

class CTransaction:
    def __init__(self,version=1,timestamp="0",txins=[],txouts = [],selfhash="",txtype=1):
        '''
        txtype=1, 版权交易
        txtype=2,新版权加入区块链
        txtype=3,版权授权
        '''
        self.__version=version
        self.__txtype=txtype
        self.__selfhash=selfhash
        self.__timestamp=timestamp
        #CTxIn 列表
        self.__txins = txins

        # CTxOut 列表 
        self.__txouts = txouts
    @property
    def txtype(self):
        return self.__txtype

    @property
    def selfhash(self):
        return self.__selfhash

    @selfhash.setter
    def selfhash(self,value):
        self.__selfhash =value

    @property
    def txins(self):
        return self.__txins

    @txins.setter
    def txins(self,value):
        self.__txins =value
    
    @property
    def txouts(self):
        return self.__txouts

    @txouts.setter
    def txouts(self,value):
        self.__txouts =value

    
    def isAddCopyRightToTheChainTx(self):
        if self.__txtype==2 and len(self.txins) == 1 and self.txins[0]["prevout"]["txhash"] == "The is a transanction which add the new copyright to the chain" and self.txins[0]["prevout"]["outindex"] == -1:
            coutP = dto.transaction.COutPoint("The is a transanction which add the new copyright to the chain",-1)
            coutPStr = coutP.serializeToJsonStr() 
            scriptPubKeyObj = modules.script.CScriptPubKey(modules.blockchain.CBlockchain.copyrightmanageraccount)
            scriptSigObj=modules.script.CScriptSig.deserializeFromPyObject(self.txins[0]['scriptSig'])
            is_verify=scriptPubKeyObj.valid(coutPStr,scriptSigObj)
            if is_verify:
                return True
            else:
                return False

        else:
            return False
   #Object——>jsonStr
    def serializeToJsonStr(self):
        sttr=json.dumps(self, default=lambda obj: obj.__dict__)
        return sttr.replace("_CTransaction__","").replace("_CTxIn__","").replace("_COutPoint__","").replace("_CTxOut__","").replace("_CScriptPubKey__","").replace("_CScriptSig__","")
    #jsonStr——> Object
    @classmethod
    def deserializeFromJsonStr(cls,jsonStrobjectdata):
        d = json.loads(jsonStrobjectdata)
        #print(d['txins'])
        return  cls(d['version'],d['timestamp'],d['txins'],d['txouts'],d['selfhash'],d['txtype'])
       
    #Object——>Python Object
    def serializeToPyObject(self):
        return json.loads(self.serializeToJsonStr())
    
    #Python Object——>Object
    @classmethod
    def deserializeFromPyObject(cls,pyObject):
       return cls.deserializeFromJsonStr(json.dumps(pyObject))
    @staticmethod
    def ifTheCopyrightcontentKeyIsRight(copyrightcontent,contenttype):
        if contenttype==1 or contenttype==2:
            required=['copyrightName','workType','author','own','place','finishDate','describe','effectiveDate','periodOfvalidity']
            if not all(k in copyrightcontent for k in required):
                return False
            else:
                return True
        if contenttype==3:
            required=['copyrightName','workType','author','own','place','finishDate','describe','effectiveDate','periodOfvalidity','user']
            if not all(k in copyrightcontent for k in required):
                return False
            else:
                return True
        
        return False
        
    
    @staticmethod
    def compareCopyrightcontent(copyrightcontentA,copyrightcontentB,txtypeA=1,txtypeB=1):
        
        if  dto.transaction.CTransaction.ifTheCopyrightcontentKeyIsRight(copyrightcontentA,txtypeA) and dto.transaction.CTransaction.ifTheCopyrightcontentKeyIsRight(copyrightcontentB,txtypeB):
                copyrightcontentA=json.loads(copyrightcontentA)
                copyrightcontentB=json.loads(copyrightcontentB)
                if copyrightcontentA['copyrightName']!=copyrightcontentB['copyrightName'] or copyrightcontentA['workType']!=copyrightcontentB['workType'] or copyrightcontentA['author']!=copyrightcontentB['author']:
                    return False
                if copyrightcontentA['place']!=copyrightcontentB['place'] or copyrightcontentA['finishDate']!=copyrightcontentB['finishDate'] or copyrightcontentA['describe']!=copyrightcontentB['describe']:
                    return False
                if copyrightcontentA['effectiveDate']!=copyrightcontentB['effectiveDate'] or copyrightcontentA['periodOfvalidity']!=copyrightcontentB['periodOfvalidity']:
                    return False
                return True

                if  txtypeA==1 and txtypeB==1:
                    if copyrightcontentA['own']==copyrightcontentB['own']:
                        return False
                    else:
                        return True
                if  txtypeA==3 and txtypeB==1:
                    return True
                if txtypeA==3 and txtypeB==2:
                    return True
                if txtypeA==2 and txtypeB==2:
                    return True
                if txtypeA==3 and txtypeB==3:
                    if copyrightcontentA['user']==copyrightcontentB['user']:
                        return False
                    else:
                        return True
                return False
                
        else:
            return False

    @staticmethod
    def ifspendTheRightTxtype(pretxtype,txtype):
        if pretxtype==1:
            if txtype==1 or txtype==3:
                return True
            else:
                return False
        if pretxtype==2:
            if txtype==1 or txtype==3:
                return True
            else:
                return false 
        if pretxtype==3:
            if txtype==3:
                return True
            else:
                return False

        return False
            
    @staticmethod
    def valid(tx):
        '''
        @tx  python object dict
        '''
        tx=copy.deepcopy(tx)
       
        copyrightcontent = []
        spendtxtypes=[]
        recieveAmount = 0
    
        if tx['selfhash'] == util.chash.CHash.getTransactionHash(tx):
            tx1 = dto.transaction.CTransaction.deserializeFromPyObject(tx)
            if tx1.isAddCopyRightToTheChainTx() == False :
                for txin in tx['txins']:
                    storeinfo = modules.db.CDb.getValueByKey("chainIndexFile",txin["prevout"]["txhash"])
                    if storeinfo!=None:
                        blckheight= int(storeinfo.split(',')[3])
                        t = modules.blockchain.CBlockchain.getChainHeight() - blckheight
                        #经过6个确认才能使用
                        if t>=5:
                            unSpendOutStr = modules.db.CDb.getValueByKey("chainStateFile",txin["prevout"]["txhash"])
                            if unSpendOutStr !=None:
                                unSpendOut =  dto.utx.CUTx.deserializeFromJsonStr(unSpendOutStr)
                                 
                                if dto.transaction.CTransaction.ifspendTheRightTxtype(unSpendOut.txtype,tx['txtype']): 
                                    
                                    unSpendOuts = unSpendOut.unSpendOuts
                                    for outInfo in unSpendOuts:
                                        if outInfo['outindex'] == txin['prevout']['outindex']:
                                            scriptPubKey = outInfo['txout']['scriptPubKey']
                                            scriptPubKeyObj=modules.script.CScriptPubKey.deserializeFromPyObject(scriptPubKey)
                
                                            coutP = dto.transaction.COutPoint(txin['prevout']['txhash'],txin['prevout']['outindex'])
                                            coutPStr = coutP.serializeToJsonStr()
                                            scriptSigObj=modules.script.CScriptSig.deserializeFromPyObject(txin['scriptSig'])
                                            is_verify=scriptPubKeyObj.valid(coutPStr,scriptSigObj)
                                            if is_verify:
                                                spendtxtypes.append(unSpendOut.txtype) 
                                                copyrightcontent.append(outInfo['txout']['content']) 
                                            else:
                                                return False
                                        else:
                                            return False
                                else:
                                    return False
                            else:
                                return False
                        else:
                            return False
                    else:
                        return False
                for txout in tx['txouts']:
                    if util.chash.CHash.ifCopyRightContentHashIsRight(txout["content"],txout["value"]):
                        if CTransaction.compareCopyrightcontent(txout["content"],copyrightcontent[0],tx['txtype'],spendtxtypes[0]):
                            return True
                        else:
                            return False
                    else:
                        return False
                  
                    
                    
                return False
            else:
                # mineReward=modules.appconfig.CAppconfig.configFromFile['mineReward']
                # if tx['txouts'][0]['value']==mineReward:
                #     return True
                # else:
                #     return False
                return True

        else:
            return False
